//
// Created by ningjian on 18-6-2.
//

#ifndef RTPPUSHER_RTPPACKAGE_HPP
#define RTPPUSHER_RTPPACKAGE_HPP


#include <cstdint>
#include <list>

enum PackageDataType {
    F_I = 0x00,
    F_P = 0x01,
    F_B = 0x02,
    A_F = 0x03,
    T_T = 0x04
};

enum SubPackageFlag {
    SPF_ATOM = 0x00,
    SPF_FIRST = 0x01,
    SPF_LAST = 0x02,
    SPF_MID = 0x03
};

enum PTType{
    PT_AAC = 25,
    PT_MP3 = 25,
    PT_H264 = 98,
    PT_H265 = 99,
};

class RTPPackage {
public:


    RTPPackage();
    ~RTPPackage();

    static void GetRTPPackagesOnFrameData(std::list<RTPPackage *> &outs,
                                          uint16_t &sn,
                                          uint8_t sim[6],
                                          uint8_t ch,
                                          uint8_t pt,
                                          uint8_t dtype,
                                          uint64_t ts,
                                          size_t frame_len,
                                          uint8_t *frame_data,
                                          uint16_t last_I_I = 0,
                                          uint16_t last_F_I = 0);

    uint8_t *getSendData(size_t &out_len);

public:
    //帧头标识 固定为 0x30 0x31 0x63 0x64
    uint8_t FH[4]{0x30, 0x31, 0x63, 0x64};
    //版本(V)：2比特 此域定义了RTP的版本。此协议定义的版本是2
    uint8_t V{2};
    //填充(P)：1比特 若填料比特被设置，则此包包含一到多个附加在末端的填充比特，填充比特不算作负载的一部分。填充的最后一个字节指明可以忽略多少个填充比特。填充可能用于某些具有固定长度的加密算法，或者用于在底层数据单元中传输多个RTP包。
    uint8_t P{0};

    //扩展(X)：1比特 若设置扩展比特，固定头(仅)后面跟随一个头扩展
    uint8_t X{0};

    //CSRC计数(CC)：4比特   CSRC计数包含了跟在固定头后面CSRC识别符的数目。
    uint8_t CC{1};

    //标志(M)：1比特 标志的解释由具体协议规定。它用来允许在比特流中标记重要的事件，如帧边界
    // H264最后一个NALU时，该值设置成1，其他都设置成0。
    uint8_t M{0};

    //负载类型(PT)：7比特 此域定义了负载的格式，由具体应用决定其解释。协议可以规定负载类型码和负载格式之间一个默认的匹配。其他的负载类型码可以通过非RTP方法动态定义。RTP发送端在任意给定时间发出一个单独的RTP负载类型；此域不用来复用不同的媒体流。
    //H264类型为96
    uint8_t PT{0};

    //序列号（sequence number）：16比特 每发送一个RTP数据包，序列号加1，接收端可以据此检测丢包和重建包序列。序列号的初始值是随机的(不可预测)，以使即便在源本身不加密时(有时包要通过翻译器，它会这样做)，对加密算法泛知的普通文本攻击也会更加困难。
    uint16_t SN{0};

    //终端设备 SIM 卡号
    uint8_t SIM[6];

    //逻辑通道号
    uint8_t CH{1};

    //4 BITS
    //    0000：视频 I 帧；
    //    0001：视频 P 帧；
    //    0010：视频 B 帧；
    //    0011：音频帧；
    //    0100：透传数据
    uint8_t DataType;

    //分包处理标记
    //    0000：原子包，不可被拆分；
    //    0001：分包处理时的第一个包；
    //    0010：分包处理时的最后一个包；
    //    0011：分包处理时的中间包
    uint8_t SubpackageFlag;

    //时间戳（timestamp） 64比特时间戳反映了RTP数据包中第一个字节的采样时间。时钟频率依赖于负载数据格式，并在描述文件（profile）中进行描述。也可以通过RTP方法对负载格式动态描述
    uint64_t TS{0};

    //该帧与上一个关键帧之间的时间间隔，单
    //位毫秒(ms)，当数据类型为非视频帧时，则
    //没有该字段
    uint16_t Last_I_Frame_Interval;

    //该帧与上一帧之间的时间间隔，单位毫秒
    //(ms)，当数据类型为非视频帧时，则没有该
    //字段
    uint16_t Last_Frame_Interval;

    //后续数据体长度，不含此字段
    uint16_t Body_Len;

    //音 视 频 数 据 或 透 传 数 据， 长 度 不 超 过950 byte
    uint8_t *Body_Data{NULL};

private:
    size_t send_len;
    uint8_t *send_data{NULL};
};


#endif //RTPPUSHER_RTPPACKAGE_HPP
